package com.lemon.components.ant.docmaker;

import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.lemon.components.ant.docmaker.DocConverter.DocType;
import com.lemon.components.ant.docmaker.dto.DocParams;
import com.lemon.components.ant.docmaker.dto.DocReq;
import com.lemon.components.ant.docmaker.dto.DocRsp;
import com.lemon.components.ant.swagger.makeui.AntdFromSwaggerMaker;
import com.lemon.components.ant.util.TemplateUtil;
import com.system.core.security.NameUtil;

import lombok.experimental.UtilityClass;

@UtilityClass
public class ApiMakerFromDoc {
	
	public static void main(String[] args) throws Exception {
		DocReq req = ApiMakerFromDoc.Option1();
//		req.setApiurl("/saas/org/addScanMerchant");
		req.setExcelPath("C:\\Users\\Administrator\\Desktop\\w.xlsx");
		req.setComment("分页查询设备列表");
		req.setTotalRows(13);
		req.setClazzName("CameraListRsp");
		req.setPackageName("com.tancheng.farming.integration.yinshicamera.dto");
		req.setSavePath("D:\\workspace\\farming\\farming-integration\\src\\main\\java\\com\\tancheng\\farming\\integration\\yinshicamera\\dto\\");
		ApiMakerFromDoc.make(req);
	}
	
	public DocReq Option1() {
		return DocReq.builder()
			    // java属性
				.codeIndex("a")
				// 类型
				.typeIndex("b")
				// 字段长度
//				.lengthIndex(3)
				// 注释1
				.remark1Index("c")
				// 注释2
//				.remark2Index(5)
				// 是否必须传字段
				.requireIndex("d")
				// 是否必须关键字
				.requireTag("Y")
				.build();
	}
	
	private void printTestCase(DocReq req,List<DocRsp> paramList) {
		StringBuilder sb = new StringBuilder("// "+req.getComment()+"\n");
		String className = NameUtil.javaClassName(req.getClazzName());
		sb.append("@Test\npublic void "+req.getClazzName()+"() {\n");
		sb.append(className+" req = ");
		sb.append(NameUtil.javaClassName(req.getClazzName())+".builder()\n");
		for(DocRsp rsp:paramList) {
			sb.append("    //"+rsp.getRemark1()+"");
			if(rsp.getIsRequire()) {
				sb.append("(必填)");
			}
			sb.append("\n");
			sb.append("    .");
			sb.append(rsp.getCode()+"(");
			if(rsp.getType().isNumber()) {
				sb.append(123+"L)");
			} else {
				sb.append("\""+rsp.getRemark1()+"\")");
			}
			sb.append("\n");
		}
		sb.append("    .build();\n");
		sb.append("}\n");
		sb.append("__________________________________");
		System.out.println(sb.toString());
	}

	public void make(DocReq req) throws Exception {
		FileInputStream fis = new FileInputStream(req.getExcelPath());
		try (XSSFWorkbook workbook = new XSSFWorkbook(fis)) {
			List<DocRsp> paramList = new ArrayList<DocRsp>();
			XSSFSheet sheet = workbook.getSheetAt(0);
			int totalRow;
			if(req.getTotalRows()==null || req.getTotalRows()==0) {
				totalRow = sheet.getLastRowNum();
			} else {
				totalRow = req.getTotalRows();
			}
			System.out.println("共计"+totalRow+"行。");
			int i = 0;
			if(req.isIgnoreHeader())
				i = 1;
			String previousCode=null;
			for (; i < totalRow; i++) {
				XSSFRow row = sheet.getRow(i);
				// 必传字段
				boolean isRqurie = false;
				if(req.getRequireIndex() != null) {
					String requrieStr = getString(row.getCell(getCodeIndex(req.getRequireIndex())));
					if(StringUtils.isNotBlank(requrieStr) && requrieStr.equalsIgnoreCase(req.getRequireTag())) {
						isRqurie = true;
					}
				}
				String srccode = getString(row.getCell(getCodeIndex(req.getCodeIndex())));
				if(StringUtils.isNotBlank(srccode))previousCode = srccode;
				
				String remark1 = getString(row.getCell(getCodeIndex(req.getRemark1Index())));
				String code;
				if(StringUtils.isBlank(srccode)&&StringUtils.isBlank(remark1)) {
					continue;
				} else {
					code = NameUtil._2JavaName(srccode);
				}
				DocRsp item = new DocRsp();
				item.setCode(code);
				item.setSrcCode(srccode);
				DocType docType = DocConverter.typeConvert(getString(row.getCell(getCodeIndex(req.getTypeIndex()))));
				item.setType(docType);
				if(docType.isContainLength()) {
					item.setLength(docType.getTypeLength());
				}
				if(req.getLengthIndex() != null) {
					item.setLength(getInteger(row.getCell(getCodeIndex(req.getLengthIndex()))));
				} else {
					item.setLength(docType.getTypeLength());
				}
				if(req.getRemark1Index()!=null)
					item.setRemark1(getString(row.getCell(getCodeIndex(req.getRemark1Index()))));
				if(req.getRemark2Index() != null)
					item.setRemark2(getString(row.getCell(getCodeIndex(req.getRemark2Index()))));
				item.setIsRequire(isRqurie);
				if(StringUtils.isBlank(srccode)) {
					String tmpstr = previousCode;
					DocRsp tempItem = paramList.stream().filter(f->f.getCode().equalsIgnoreCase(tmpstr)).findAny().get();
					tempItem.setRemark1(tempItem.getRemark1()+" "+item.getRemark1());
				} else {
					paramList.add(item);
				}
			}
			paramList.forEach(item->{
				item.setRemark1(item.getRemark1().replaceAll("\"", "“"));
			});
			DocParams docParams = new DocParams();
			docParams.setReq(req);
			docParams.setRsp(paramList);
			printMySQLField(req,paramList);
			printTestCase(req,paramList);
			TemplateUtil.getInstance(AntdFromSwaggerMaker.class.getResource("/code/").getFile()).build(
					"/vue/ApiOptBeanTemplate.ftl", 
					req.getSavePath()+StringUtils.capitalize(req.getClazzName())+".java",
					docParams);
			workbook.close();
		}
		fis.close();
	}
	
	public void printMySQLField(DocReq req,List<DocRsp> paramList) {
		StringBuilder modifySQL = new StringBuilder("ALTER TABLE `liaofarm_liaoken`.`merchant`\n");
		String filedName="";
		for(DocRsp rsp:paramList) {
			modifySQL.append("ADD COLUMN `"+NameUtil.javaName2_(rsp.getCode())+"` "+DocConverter.printDBType(rsp.getType().getTypeName(),rsp.getLength())+" ");
			if(rsp.getIsRequire()) {
				modifySQL.append("NOT NULL ");
			} else {
				modifySQL.append("NULL ");
			}
			modifySQL.append("COMMENT '"+rsp.getRemark1()+"' ");
			modifySQL.append("AFTER `"+filedName+"`,\n");
			filedName=NameUtil.javaName2_(rsp.getCode());
		}
		System.out.println(modifySQL.toString());
	}
	
	public String getString(XSSFCell cell) {
		
		if(cell == null)
			return StringUtils.EMPTY;
		
		switch (cell.getCellTypeEnum()) {
			case NUMERIC: 
				double d = cell.getNumericCellValue();
				return String.valueOf(d);
			case STRING: 
				return cell.getStringCellValue().trim();
			case BLANK: 
				return "";
			case BOOLEAN: 
				return String.valueOf(cell.getBooleanCellValue());
			default:
				return StringUtils.EMPTY;
		}
	}
	
	public Double getNumeric(XSSFCell cell) {
		if(cell == null)
			return CELLZERO;
		switch (cell.getCellTypeEnum()) {
			case NUMERIC: 
				return cell.getNumericCellValue();
			case STRING: 
				try {
					String tmp = cell.getStringCellValue();
					return Double.valueOf(tmp);
				} catch (Exception e) {
					return CELLZERO;
				}
			case BLANK: 
				return CELLZERO;
			default:
				return CELLZERO;
		}
	}
	
	public Integer getInteger(XSSFCell cell) {
		Double tmp = getNumeric(cell);
		if(tmp == null)
			return 0;
		else
			return getNumeric(cell).intValue();
	}
	
	private static int getCodeIndex(String code) {
		return Arrays.binarySearch(columnsCode, code.toLowerCase());
	}
	
	private static final double CELLZERO = (double)0;
	private static String[] columnsCode = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"};
}
